<template>
  <div class="container">
    <h1>屏幕+系统声音+麦克风推流</h1>
    <video ref="localVideo" autoplay muted></video>
    <button @click="startStream" :disabled="isStreaming">开始推流</button>
    <button @click="stopStream" :disabled="!isStreaming">停止推流</button>
    <p v-if="errorMessage" class="error">{{ errorMessage }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      screenStream: null,
      systemAudioStream: null,
      micStream: null,
      combinedStream: null,
      peerConnection: null,
      isStreaming: false,
      errorMessage: '',
    };
  },
  methods: {
    async captureScreen() {
      try {
        this.screenStream = await navigator.mediaDevices.getDisplayMedia({
          video: true,
          audio: true
        });
      } catch (error) {
        throw new Error(`屏幕捕获失败: ${error.message}`);
      }
    },
    async captureSystemAudio() {
      try {
        const audioContext = new AudioContext();
        const destination = audioContext.createMediaStreamDestination();
        const source = audioContext.createMediaStreamSource(await navigator.mediaDevices.getUserMedia({ audio: true }));
        source.connect(destination);
        this.systemAudioStream = destination.stream;
      } catch (error) {
        throw new Error(`系统声音捕获失败: ${error.message}`);
      }
    },
    async captureMic() {
      try {
        this.micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
      } catch (error) {
        throw new Error(`麦克风捕获失败: ${error.message}`);
      }
    },
    combineStreams() {
      const combined = new MediaStream();

      // 添加屏幕视频轨道
      this.screenStream.getVideoTracks().forEach(track => combined.addTrack(track));

      // 合并音频轨道
      const audioContext = new AudioContext();
      const destination = audioContext.createMediaStreamDestination();

      // 添加系统音频
      if (this.systemAudioStream) {
        const systemSource = audioContext.createMediaStreamSource(this.systemAudioStream);
        systemSource.connect(destination);
      }

      // 添加麦克风音频
      if (this.micStream) {
        const micSource = audioContext.createMediaStreamSource(this.micStream);
        micSource.connect(destination);
      }

      // 将混合后的音频添加到最终流
      destination.stream.getAudioTracks().forEach(track => combined.addTrack(track));

      return combined;
    },
    async startStream() {
      try {
        // 捕获所有媒体
        await this.captureScreen();
        await this.captureSystemAudio();
        await this.captureMic();

        // 合并流
        this.combinedStream = this.combineStreams();
        this.$refs.localVideo.srcObject = this.combinedStream;

        // 创建 RTCPeerConnection
        this.peerConnection = new RTCPeerConnection();

        // 添加音视频轨道
        this.combinedStream.getTracks().forEach(track =>
          this.peerConnection.addTrack(track, this.combinedStream)
        );

        // 创建 SDP Offer
        const offer = await this.peerConnection.createOffer();
        await this.peerConnection.setLocalDescription(offer);

        // 发送 WHIP 请求
        const response = await fetch('http://106.54.211.74:1985/rtc/v1/whip/?app=live&stream=livestream5', {
          method: 'POST',
          body: offer.sdp,
          headers: { 'Content-Type': 'application/sdp' },
        });

        if (!response.ok) {
          throw new Error(`服务器返回错误: ${response.status} ${response.statusText}`);
        }

        const responseBody = await response.text();
        if (!responseBody) {
          throw new Error('服务器返回空响应');
        }

        // 解析 SDP Answer
        const answer = { type: 'answer', sdp: responseBody };
        await this.peerConnection.setRemoteDescription(answer);

        this.isStreaming = true;
        this.errorMessage = '';
        console.log('推流成功！');
      } catch (error) {
        this.errorMessage = `推流失败: ${error.message}`;
        console.error('推流失败:', error);
      }
    },
    stopStream() {
      if (this.combinedStream) {
        this.combinedStream.getTracks().forEach(track => track.stop());
        this.combinedStream = null;
      }
      if (this.peerConnection) {
        this.peerConnection.close();
        this.peerConnection = null;
      }
      this.isStreaming = false;
      this.$refs.localVideo.srcObject = null;
      console.log('推流已停止');
    },
  },
};
</script>

<style>
.container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  text-align: center;
}

video {
  width: 100%;
  max-width: 500px;
  height: auto;
  background: #000;
  margin: 20px 0;
}

button {
  margin: 5px;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
}

.error {
  color: red;
  margin-top: 10px;
}
</style>
